package com.lancoo.ccas52.arrangecourse.dataprocess;

import com.lancoo.ccas52.arrangecourse.entities.ClassHour;
import com.lancoo.ccas52.arrangecourse.entities.CourseUnit;
import com.lancoo.ccas52.arrangecourse.entities.TimeslotRoom;
import com.lancoo.ccas52.entity.Schedule;
import com.lancoo.ccas52.pojo.dto.ArrangePeriod;
import com.lancoo.ccas52.pojo.dto.ArrangeScheduleDto;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Description 处理排课课时以及课表之间数据的转换
 * @Author Fortysun
 * @Date 2023/5/16 14:45
 **/
@Slf4j
public class ClassHourScheduleConvert {
    /**
     * 将排课的上课单元对象，转换成排课用的课时对象，用来处理冲突检测；
     * @param scheduleList 数据库课表对象
     * @param timeslotList 课时列表
     * @return
     */
    public CopyOnWriteArrayList<ClassHour> convertToClassHourList(List<ArrangeScheduleDto> scheduleList,
                                                  List<ArrangePeriod> timeslotList) {
        CopyOnWriteArrayList<ClassHour> classHourList = new CopyOnWriteArrayList<>();
        if (scheduleList == null || scheduleList.isEmpty()) {
            log.info("ClassHourScheduleConvert--convertToClassHourList: 需要转换的排课上课单元列表为空~！！");
            return classHourList;
        }

        //课程单元id
        int courseUnitId = 1;
        for (ArrangeScheduleDto scheduleDto : scheduleList) {
            ClassHour classHour = scheduleToClassHour(scheduleDto, courseUnitId++, timeslotList);
            classHourList.add(classHour);
        }

        return classHourList;
    }

    /**
     * 将排课单元对象，转换成排课使用的课时对象；
     * @param scheduleDto 数据库课表对象
     * @param courseUnitId 算法课表对象中的课程排课单元id
     * @param timeslotList 课时列表
     * @param classHourList 已经生成的算法排课课表列表
     * @return
     */
    private ClassHour scheduleToClassHour(ArrangeScheduleDto scheduleDto,
                                          Integer courseUnitId,
                                          List<ArrangePeriod> timeslotList) {
        if (scheduleDto == null) {
            log.error("ClassHourScheduleConvert--scheduleToClassHour: 上课单元对象为空~！！");
            return null;
        }
        //初始化课表对象
        ClassHour classHour = new ClassHour();
        //初始化课表的排课单元对象
        CourseUnit courseUnit = initCourseUnit(courseUnitId, scheduleDto);
        //将排课单元添加到课表对象
        classHour.setCourseUnit(courseUnit);

        //只处理分配了教室课时的排课单元
        if (scheduleDto.getRoomId() != null && scheduleDto.getTimeCode() != null) {

            //初始化，教室课时分组信息
            TimeslotRoom timeslotRoom = initTimeslotRoom(courseUnitId, scheduleDto, timeslotList);
            //设置给课表对象
            classHour.setTimeslotRoom(timeslotRoom);
        }

        return classHour;
    }

    /**
     * 初始化课表排课单元信息
     * @param courseUnitId 教室课时分组id
     * @param scheduleDto 数据库保存的课表对象
     * @return
     */
    private CourseUnit initCourseUnit(Integer courseUnitId,
                                      ArrangeScheduleDto scheduleDto) {
        CourseUnit courseUnit = new CourseUnit();
        courseUnit.setUnitId(courseUnitId);
        courseUnit.setClassWeeks(scheduleDto.getWeek());
        courseUnit.setRoomType(scheduleDto.getRoomType());
        courseUnit.setStudentIds(scheduleDto.getStudentIds());
        courseUnit.setTeacherIds(scheduleDto.getTeacherIds());
        courseUnit.setTeachingClassId(scheduleDto.getTeachingClassId());
        courseUnit.setTeachingClassName(scheduleDto.getTeachingClassName());
        courseUnit.setTeachingClassSize(scheduleDto.getStudentNumber());
        courseUnit.setTeachingClassType(scheduleDto.getTeachingClassType());
        courseUnit.setTeachingType(scheduleDto.getHourType());
        courseUnit.setConnectSection(scheduleDto.getConnectSection());
        courseUnit.setTaskId(scheduleDto.getTaskId());
        courseUnit.setCourseType(scheduleDto.getFlag());
        courseUnit.setCampusId(scheduleDto.getCampusId());
        courseUnit.setCourseId(scheduleDto.getCourseId());
        courseUnit.setCourseName(scheduleDto.getCourseName());
        courseUnit.setSubTeachingClassId(scheduleDto.getSubTeachingClassId());
        courseUnit.setCollegeId(scheduleDto.getCollegeId());
        courseUnit.setGroupIdent(scheduleDto.getGroupIdent());

        return courseUnit;
    }


    /**
     * 初始化教室课时分组信息
     * @param courseUnitId 教室课时分组id
     * @param scheduleDto 数据库保存的课表对象
     * @param timeslotList 课时列表
     * @return
     */
    private TimeslotRoom initTimeslotRoom(Integer courseUnitId,
                                          ArrangeScheduleDto scheduleDto,
                                          List<ArrangePeriod> timeslotList) {
        TimeslotRoom timeslotRoom = new TimeslotRoom();
        timeslotRoom.setTimeslotRoomId(courseUnitId);
        timeslotRoom.setRoomId(scheduleDto.getRoomId());
        timeslotRoom.setRoomName(scheduleDto.getRoomName());
        timeslotRoom.setCapacity(scheduleDto.getRoomNum());
        timeslotRoom.setRoomType(scheduleDto.getRoomTypeArrange());
        String timeslotCode = scheduleDto.getTimeCode();
        timeslotRoom.setTimeslotCode(timeslotCode);
        timeslotRoom.setTimeslotName(scheduleDto.getCodeName());
        //获取课时对象，用来初始化dayNo、period、periodType
        ArrangePeriod timeslot = getTimeslotByCode(timeslotCode, timeslotList);
        timeslotRoom.setPeriod(timeslot.getPeriod());
        timeslotRoom.setPeriodType(timeslot.getPeriodType());
        timeslotRoom.setDayNo(timeslotCode.substring(0,2));
        timeslotRoom.setWeeks(scheduleDto.getWeek());
        timeslotRoom.setCampusId(scheduleDto.getCampusId());

        return timeslotRoom;
    }

    /**
     * 根据课时编码，获取指定的课时对象信息
     * @param timeslotCode 课时编码信息
     * @param timeslotList 课时列表信息
     * @return
     */
    private ArrangePeriod getTimeslotByCode(String timeslotCode,
                                            List<ArrangePeriod> timeslotList) {
        if (timeslotList != null && !timeslotList.isEmpty()) {
            for (ArrangePeriod timeslot : timeslotList) {
                if (timeslotCode.equals(timeslot.getTimeCode())) {
                    return timeslot;
                }
            }
        }
        log.error("ClassHourScheduleConvert--getTimeslotByCode: 指定课时编码的课时对象信息获取失败~！！");
        return null;
    }

    /**
     * 将排课的课时对象，转换成数据库表实体类对象；
     * @param classHourMap 需要转换的课时列表信息
     * @return
     */
    public  List<Schedule> convertToScheduleList(ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap) {
        List<Schedule> scheduleList = new ArrayList<>();
        //统计不同类型的课时，对应的课时的冲突次数
        for (Map.Entry entry : classHourMap.entrySet()) {
            scheduleList.addAll(hourListToScheduleList((CopyOnWriteArrayList<ClassHour>)entry.getValue()));
        }

        return scheduleList;
    }

    /**
     * 将排课单元列表信息，转换成课表，过滤掉不是本排课计划的排课单元
     * @param classHourList 课表列表信息
     * @return
     */
    private List<Schedule> hourListToScheduleList(CopyOnWriteArrayList<ClassHour> classHourList) {
        List<Schedule> scheduleList = new ArrayList<>();
        //遍历课表列表
        for (ClassHour classHour : classHourList) {
            //如果排课单元不为空，并且计划id相等
            if (classHour != null
                    && classHour.getCourseUnit() != null) {
                //将生成的数据库课表对象，加入列表
                scheduleList.add(new Schedule(classHour));
            }
        }

        return scheduleList;
    }
}
